﻿using System;
using System.Collections.Generic;
using EOS.Framework.Kernel;
using NHibernate;
using NHibernate.Criterion;

namespace EOS.Framework.Data
{
    public class BaseDao<T> : IBaseDao<T> where T : BaseDomainObject
    {
        protected ISession Session
        {
            get { return ServiceLocator.Current.GetInstance<ISession>(); }
        }

        #region IBaseDao<T> Members

        /// <summary>
        /// Gets the specified id.
        /// </summary>
        /// <param name="id">The id.</param>
        /// <returns></returns>
        public virtual T Get(int id)
        {
            return Session.Get<T>(id);
        }

        /// <summary>
        /// Saves the or update.
        /// </summary>
        /// <param name="entity">The entity.</param>
        public void SaveOrUpdate(T entity)
        {
            SaveOrUpdate(entity, false);
        }

        /// <summary>
        /// Saves the or update.
        /// </summary>
        /// <param name="entity">The entity.</param>
        public virtual void SaveOrUpdate(T entity, bool commit)
        {
            if (entity == null)
            {
                throw new ArgumentNullException("entity");
            }

            if (commit)
            {
                ITransaction transaction = Session.BeginTransaction();
                Session.SaveOrUpdate(entity);

                transaction.Commit();
            }
            else
            {
                Session.SaveOrUpdate(entity);
            }
        }

        /// <summary>
        /// Deletes the specified entity.
        /// </summary>
        /// <param name="entity">The entity.</param>
        public virtual void Delete(T entity)
        {
            ITransaction tx = Session.BeginTransaction();
            Session.Delete(entity);

            tx.Commit();
        }

        /// <summary>
        /// Finds all.
        /// </summary>
        /// <returns></returns>
        public virtual IList<T> FindAll()
        {
            return Session.CreateCriteria(typeof(T)).List<T>();
        }

        public virtual IList<T> Find(int firstResult, int limit)
        {
            return Session.CreateCriteria(typeof(T)).SetFirstResult(firstResult).SetMaxResults(limit).List<T>();
        }

        /// <summary>
        /// Count all entries.
        /// </summary>
        /// <returns>Number of entries.</returns>
        public virtual int Count()
        {
            return Session.CreateCriteria(typeof(T)).SetProjection(Projections.RowCount()).UniqueResult<int>();
        }

        #endregion
    }
}
